package javachongkao.面向对象上.继承覆盖综合练习;

import java.text.DecimalFormat;
import java.util.*;
//7-6 jmu-Java-03面向对象-06-继承覆盖综合练习-Person、Student、Employee、Company
//定义Person抽象类，Student类、Company类，Employee类。
//
//Person类的属性：String name, int age, boolean gender
//Person类的方法:
//
//public Person(String name, int age, boolean gender);
//public String toString();         //返回"name-age-gender"格式的字符串
//public boolean equals(Object obj);//比较name、age、gender,都相同返回true,否则返回false
//
//Student类继承自Person，属性:String stuNo, String clazz
//Student类的方法:
//
/// /建议使用super复用Person类的相关有参构造函数
//public Student(String name, int age, boolean gender, String stuNo, String clazz);
//public String toString();         //返回 “Student:person的toString-stuNo-clazz”格式的字符串
//public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true，则继续比较stuNo与clazz。
//Company类属性：String name
//Company类方法:
//
//public Company(String name);
//public String toString();         //直接返回name
//public boolean equals(Object obj);//name相同返回true
//Employee类继承自Person，属性：Company company, double salary
//Employee类方法：
//
////建议使用super复用Person类的相关有参构造函数
//public Employee(String name, int age, boolean gender, double salary, Company company);
//public String toString();         //返回"Employee:person的toString-company-salary"格式的字符串
//public boolean equals(Object obj);//首先调用父类的equals方法,如果返回true。再比较company与salary。

////比较salary属性时，使用DecimalFormat df = new DecimalFormat("#.#");保留1位小数
//编写equals方法重要说明：
//
//对Employee的company属性的比较。要考虑传入为null的情况。如果company不为null且传入为null，返回false
//对所有String字符类型比较时，也要考虑null情况。
//提示
//
//排序可使用Collections.sort
//equals方法要考虑周全
//main方法说明
//创建若干Student对象、Employee对象。
//输入s，然后依次输入name age gender stuNo clazz创建Student对象。
//输入e，然后依次输入name age gender salary company创建Employee对象。
//然后将创建好的对象放入List<Person> personList。输入其他字符，则结束创建。
//创建说明: 对于String类型，如果为null则不创建对象，而赋值为null。对于company属性，如果为null则赋值为null，否则创建相应的Company对象。
//
//对personList中的元素实现先按照姓名升序排序，姓名相同再按照年龄升序排序。提示：可使用Comparable<Person>或Comparator<Person>
//
//接受输入，如果输入为exit则return退出程序，否则继续下面步骤。
//
//将personList中的元素按照类型分别放到stuList与empList。注意：不要将两个内容相同的对象放入列表（是否相同是根据equals返回结果进行判定）。
//
//输出字符串stuList，然后输出stuList中的每个对象。
//
//输出字符串empList，然后输出empList中的每个对象。
//
//1-3为一个测试点
//4-6为一个测试点
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //创建集合，存储元素
        List<Person> personList = new ArrayList<>();
        while(true){
            String choice = sc.next();
            if("s".equals(choice)){
                String name = sc.next();
                int age = sc.nextInt();
                boolean gender = "true".equals(sc.next());
                String stuNo = sc.next();
                String clazz = sc.next();
                personList.add(new Student(name,age,gender,stuNo,clazz));
            }else if("e".equals(choice)){
                String name = sc.next();
                int age = sc.nextInt();
                boolean gender = "true".equals(sc.next());
                double salary = sc.nextDouble();
                Company company = new Company(sc.next());

                personList.add(new Employee(name,age,gender,company,salary));
            }else{
                break;
            }
        }
    /*
    利用Collections工具类里的sort方法，这里我用的是匿名内部类的方式书写的，可以转成lambda表达
    式，不过转完之后会让人难以理解，所以我就不转了
    */
        Collections.sort(personList, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int i = o1.name.compareTo(o2.name);
                i = i==0 ? o1.age-o2.age : i;
                return i;
            }
        });
        //增强for对集合进行遍历打印
        for (Person person : personList) {
            System.out.println(person.toString());
        }
        String choice = sc.next();
        if("exit".equals(choice)){
            //手动安全结束虚拟机工作
            System.exit(0);
        }

        //创建两个集合
        ArrayList<Student> stuList = new ArrayList<>();
        ArrayList<Employee> empList = new ArrayList<>();

        for (Person person : personList) {
            //用instanceof判断能否转成Student类
            if(person instanceof Student){
                if(ExistsStu(stuList,person)){
                    stuList.add((Student)person);
                }
            }else{
                if(ExistsEmp(empList,person)){
                    empList.add((Employee)person);
                }
            }
        }
        System.out.println("stuList");
        for (Student student : stuList) {
            System.out.println(student.toString());
        }
        System.out.println("empList");
        for (Employee employee : empList) {
            System.out.println(employee.toString());
        }

    }
    //判断empList是否存在该元素
    private static boolean ExistsEmp(ArrayList<Employee> empList, Person person) {
        for (Employee employee : empList) {
            if(employee.equals(person)){
                return false;
            }
        }
        return true;
    }

    //判断stuList是否存在该元素
    private static boolean ExistsStu(ArrayList<Student> stuList, Person person) {
        for (Student student : stuList) {
            if(student.equals(person)){
                return false;
            }
        }
        return true;
    }

}
//抽象类Person
abstract class Person{
    String name;
    int age;
    boolean gender;

    public Person(String name, int age, boolean gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public Person() {
    }

    @Override
    public String toString() {
        return name+"-"+age+"-"+gender;
    }

    @Override
    public boolean equals(Object obj) {
        Person p1 = (Person)obj;
        if(p1==null){
            return false;
        }
        if(p1.name==null){
            return false;
        }
        if(!this.name.equals(p1.name)){
            return false;
        }
        if(!(this.age==p1.age)){
            return false;
        }
        return this.gender == p1.gender;
    }

}

//学生类
class Student extends Person{
    String stuNo;
    String clazz;

    public Student(String name, int age, boolean gender, String stuNo, String clazz) {
        super(name, age, gender);
        this.stuNo = stuNo;
        this.clazz = clazz;
    }

    @Override
    public String toString() {
        return "Student:"+super.toString()+"-"+stuNo+"-"+clazz;
    }

    @Override
    public boolean equals(Object obj) {
        if(!super.equals(obj)){
            return false;
        }
        Student s1 = (Student)obj;
        if(s1==null){
            return false;
        }
        if(s1.stuNo==null){
            return false;
        }
        if(!this.stuNo.equals(s1.stuNo)){
            return false;
        }
        if(s1.clazz==null){
            return false;
        }
        return this.clazz.equals(s1.clazz);
    }

}
class Company{
    String name;

    public Company(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean equals(Object obj) {
        Company c1 = (Company)obj;
        if(c1==null){
            return false;
        }
        if(c1.name==null){
            return false;
        }
        return this.name.equals(c1.name);
    }

}
//员工类
class Employee extends Person{
    Company company;
    double salary;

    public Employee(String name, int age, boolean gender, Company company, double salary) {
        super(name, age, gender);
        this.company = company;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee:"+super.toString()+"-"+company.toString()+"-"+salary;
    }

    @Override
    public boolean equals(Object obj) {
        if(!super.equals(obj)){
            return false;
        }
        Employee e1 = (Employee)obj;
        if(e1.company==null){
            return false;
        }
        if(!this.company.name.equals(e1.company.name)){
            return false;
        }

        //这里不知道什么原因，小数对比总会返回false,所以我就用字符串的方式进行判断
        DecimalFormat df = new DecimalFormat("#.#");
        String s1 = df.format(this.salary);
        String s2 = df.format(e1.salary);

        return s1.equals(s2);
    }

}
